#!/usr/bin/python

import logging
import os
import signal
import socket
import subprocess
import time

VLC_HOST = '127.0.0.1'
VLC_PORT = 8001
VLC_ARGS = ['--extraintf=oldrc', '--rc-host=%s:%d' % (VLC_HOST, VLC_PORT),
            '--no-video-title-show']
VLC_ENCODING = 'utf-8'
VLC_ARGS.append('-f')

if os.name == 'nt':
    import win32api
    VLC_PATH = 'C:\\Program Files\\VideoLan\\VLC\\vlc.exe'
else:
    VLC_PATH = '/Applications/VLC.app/Contents/MacOS/VLC'


class VideoPlayer:
    AUDIO_LEFT = 3
    AUDIO_RIGHT = 4

    def __init__(self):
        self._vlc = subprocess.Popen([VLC_PATH] + VLC_ARGS)
        self._first_time = True
        while True:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            if s.connect_ex((VLC_HOST, VLC_PORT)) == 0:
                logging.info('Connected to VLC successfully')
                self._vlc_file = s.makefile()
                break
            logging.info('Failed to connect to VLC. Sleep one second and try '
                         'again')
            time.sleep(1)  # wait for one second and try again

    def IsPlaying(self):
        return self._Run('status').find('play state') != -1

    def Play(self, filename, channel):
        self._Run('clear')
        self._Run('add', filename)
        time.sleep(0.5)  # wait until the video starts
        if self._first_time:
            time.sleep(1.5)  # wait a little longer for the first time
            self._first_time = False
        self.SetAudioChannel(channel)

    def Stop(self):
        self._Run('clear')

    def Terminate(self):
        if os.name == 'nt':
            handle = win32api.OpenProcess(1, False, self._vlc.pid)
            win32api.TerminateProcess(handle, -1)
            win32api.CloseHandle(handle)
        else:
            os.kill(self._vlc.pid, signal.SIGTERM)

    def SetAudioChannel(self, channel):
        self._Run('achan', '%d' % channel)

    def _Run(self, cmd, args=None):
        vlc_cmd = cmd
        if args:
            vlc_cmd += ' ' + args
        vlc_cmd = vlc_cmd.encode(VLC_ENCODING)
        self._vlc_file.write(vlc_cmd + '\r\n')
        self._vlc_file.flush()
        logging.debug('send to VLC: ' + vlc_cmd)

        expected = cmd + ': returned '
        output = ''
        while True:
            line = self._vlc_file.readline().decode(VLC_ENCODING)
            if not line:
                break
            output += line
            if line.startswith(expected):
                break
        logging.debug('return from VLC: ' + output)
        return output
